#include "include/serialframe.h"
#include "include/serialbuffer.h"
#include "include/define.h"
#include <QDebug>

//链路层帧的特帧字符定义
const char SYN = 0x7E; // 同步符
const char DLE = 0x7D;  // 转义符
const char CHECK = 0xB9;
const QByteArray frameID(1,SYN);

SerialFrame::SerialFrame(QObject *parent) :
    QObject(parent)
{
}

// 从原始数据流中提取应用层数据帧
void SerialFrame::extractAPLframe()
{
    while(1)
    {
        int length = DalRecvBuffer::Instance()->getBuffer().size();
        if( length <= 0 )
            return;

        //帧头位置
        int idx1 = DalRecvBuffer::Instance()->getBuffer().indexOf(frameID);
        while( idx1 > 0 )
        {
            if( idx1 >= length-1 )
                return;
            if(  DalRecvBuffer::Instance()->getBuffer().at(idx1-1) != DLE
                 && DalRecvBuffer::Instance()->getBuffer().at(idx1+1) != SYN
                 )
                break;
            idx1 = DalRecvBuffer::Instance()->getBuffer().indexOf(frameID,idx1+1);
        }
        if( idx1 == -1 )
            return;

        //帧尾位置
        int idx2 = DalRecvBuffer::Instance()->getBuffer().indexOf(frameID,idx1+1);
        while( idx2 > 0 )
        {
            if(  DalRecvBuffer::Instance()->getBuffer().at(idx2-1) != DLE
                 && ( idx2 == length-1 || DalRecvBuffer::Instance()->getBuffer().at(idx2+1) == SYN )
                )
                break;

            idx2 = DalRecvBuffer::Instance()->getBuffer().indexOf(frameID,idx2+1);
        }
        if( idx2 == -1 )
            return;

        qDebug("idx1=%d,idx2=%d",idx1,idx2);

        QByteArray msg = DalRecvBuffer::Instance()->getBuffer().mid(idx1,idx2-idx1+1);
        //去掉头尾的标志符SYN
        msg = msg.mid(1,msg.size()-2);
        DalRecvBuffer::Instance()->getBuffer().remove(0,idx2+1);

        //判断校验码
        if( verify(msg) == false )
        {
            //校验码错误,可在此处发送信号,链接错误处理函数
            return;
        }

        // 开始提取每帧数据
        analysisFrame(msg);
    }
}

// 对链路层数据帧进行转义
void SerialFrame::analysisFrame(QByteArray &msg)
{
    int index = 0, len = msg.length()-1;
    while(index < len)
    {
        if( msg[index]==DLE )
        {
            if( msg[index+1]==DLE || msg[index+1]==SYN )
            {
                msg.remove(index,1);
            }
            else
            {
                // error
            }
        }
        index ++;
    }
    // 将转义之后得到的应用层数据帧添加到应用层接收缓冲队列
    aplRecvBuffer::Instance()->getBuffer().push_back(msg);
}

// 验证校验码
bool SerialFrame::verify(QByteArray &msg)
{
    int len = msg.size();
    char checkSum = CHECK;
    for(int i = 0; i < len; ++i )
    {
        checkSum ^= msg[i];
    }
    return checkSum==0 ? true:false;
}


// 添加校验码
void SerialFrame::addCheckSum(QByteArray &msg)
{
    char checkSum = CHECK;
    for( int i =0 ; i < msg.size(); ++i )
    {
         checkSum ^= msg[i];
    }
    if( checkSum==DLE || checkSum==SYN )
    {
        msg.push_back(DLE);
        checkSum ^= DLE;
    }
    msg.push_back(checkSum);
    msg.push_front(SYN);
    msg.push_back(SYN);
}

// 将应用层数据帧转换成链路层帧
void SerialFrame::generateDLLframe(QByteArray &msg)
{
    for( int i = 0; i < msg.size(); ++i )
    {
        if( msg[i]==DLE || msg[i]==SYN )
        {
            msg.insert(i,DLE);
            i++;
        }
    }
    addCheckSum(msg);
}
